#pragma once
#include <vector>
#include <string>
#include <unordered_map>
#include "my_lex.h"
#include <algorithm>

class Parser {
public:
    Parser() = default;

    void init(int line_nums);

    void analysis(std::vector<Token *> tokens, bool &result, std::vector<int> &faults);

    void print(bool &result, std::vector<int> &faults);

private:
    void insert(std::string non_term, std::string term, std::vector<std::string> shift);
private:
    struct PairHash {
        size_t operator()(const std::pair<std::string, std::string>& p) const {
            return std::hash<std::string>()(p.first) ^ 
                   (std::hash<std::string>()(p.second) << 1);
        }
    };
    std::vector<std::string> non_terms_;
    std::unordered_map<std::string, std::vector<std::string>> first_;
    std::unordered_map<std::string, std::vector<std::string>> follow_;
    std::unordered_map<std::pair<std::string, std::string>, std::vector<std::string>, PairHash> table_;
    std::vector<std::string> stack_;
    int line_nums_;
};